package main

import (
	"errors"
	"fmt"
)

func yc() {
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println("错了", err)
		}
	}()
	panic(errors.New("粑粑"))
}

func main() {
	// defer panic recover

	// defer 函数跑完了才走这个，定义时候就确定好了。 在返回多个具名函数还有机会在修改值。 defer后面可以跟自执行函数 defer后面也可跟语句
	// defer func() {
	// 	fmt.Println("testaa")
	// }()
	// fmt.Println("test")

	// 多个defer 定义按照后进先出的顺序执行后面定义的先执行 弹栈

	// 多个语句延时就放到匿名自执行函数 比如关闭资源  释放内存等等

	/*var a = func() int {
		var i = 0
		defer func() {
			i++
		}()
		return i
	}

	b := a()
	fmt.Println(b) // 返回0*/

	/*var a = func() (x int) {
		var i = 0
		defer func() {
			i++
		}()
		return i
	}

	b := a()
	fmt.Println(b) // 返回0*/

	// ！！！！！这个注意 defer 修改的具名返回值 无论return是否返回值，返回的都是具名的被defer修改的值。 但是defer没有修改具名值还是以return 为准
	// var a = func() (x int) {
	// 	x = 0
	// 	defer func() {
	// 		x++
	// 	}()
	// 	return 0
	// }

	// b := a()
	// fmt.Println(b) // 返回0

	// 佐证上面的结论
	// var a = func() (x int) {
	// 	a := 0
	// 	x = 0
	// 	defer func() {
	// 		a++
	// 	}()
	// 	return 999
	// }

	// b := a()
	// fmt.Println(b) // 返回0

	// 佐证只有具名返回值才能被defer接管
	// var a = func() int {
	// 	var x int
	// 	defer func() {
	// 		x++
	// 	}()
	// 	return x
	// }

	// b := a()
	// fmt.Println(b) // 返回0

	// 如果上来没赋值x的初值会延续用return 的值
	// var a = func() (x int) {

	// 	defer func() {
	// 		x++
	// 	}()
	// 	return 6
	// }

	// b := a()
	// fmt.Println(b) // 返回7

	//最后在啰嗦句 defer后面的语句定义的时候就必须确定里面的值 根据注册时候的位置的上下文

	// 异常处理

	// panic 抛出异常

	// errors.New("粑粑") 配合 panic 创建错误消息

	// 接收异常

	// yc() //保证程序能继续执行需要处理异常
	// fmt.Println("不处理异常执行不到这里")

	// 函数 返回值定义 error 可以直接返回 errors.New("") 或者 nil 由调用方处理 如果不等于nil就说明有问题  nil 主动抛出 使用端根据是否nil 来判断 和 panic 差不多只是panic 没有recover就干死程序了这个干不死

	// panic 触发需要 defer recover来处理异常

}
